package com.sas.controller;

import com.sas.common.Result;
import com.sas.entity.Schedule;
// 移除不存在的枚举导入，统一使用整数类型
import com.sas.service.ScheduleService;
import com.sas.service.SchedulingAlgorithmService;
import org.springframework.beans.factory.annotation.Autowired;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.time.LocalDate;
import java.time.LocalTime;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * 排班管理Controller
 */
@RestController
@RequestMapping("/schedule")
@Validated
public class ScheduleController {

    private static final Logger log = LoggerFactory.getLogger(ScheduleController.class);
    @Autowired
    private ScheduleService scheduleService;
    @Autowired
    private SchedulingAlgorithmService schedulingAlgorithmService;

    /**
     * 创建排班
     */
    @PostMapping
    public Result<Schedule> createSchedule(@Valid @RequestBody Schedule schedule) {
        log.info("创建排班，员工ID: {}, 房间ID: {}, 日期: {}", 
                schedule.getEmployeeId(), schedule.getRoomId(), schedule.getScheduleDate());
        try {
            // 检查排班冲突
            if (scheduleService.hasScheduleConflict(schedule)) {
                return Result.badRequest("排班时间冲突，请检查员工或房间的排班安排");
            }
            Schedule savedSchedule = scheduleService.save(schedule);
            return Result.success(savedSchedule);
        } catch (Exception e) {
            log.error("创建排班失败", e);
            return Result.error("创建排班失败: " + e.getMessage());
        }
    }

    /**
     * 根据ID查询排班
     */
    @GetMapping("/{id}")
    public Result<Schedule> getScheduleById(@PathVariable Long id) {
        log.info("查询排班，ID: {}", id);
        Optional<Schedule> schedule = scheduleService.findById(id);
        if (schedule.isPresent()) {
            return Result.success(schedule.get());
        } else {
            return Result.notFound("排班信息不存在");
        }
    }

    /**
     * 查询排班列表
     */
    @GetMapping
    public Result<List<Schedule>> getSchedules(
            @RequestParam(required = false) Long employeeId,
            @RequestParam(required = false) Long roomId,
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate scheduleDate,
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate) {
        log.info("查询排班列表，员工ID: {}, 房间ID: {}, 日期: {}", employeeId, roomId, scheduleDate);
        try {
            List<Schedule> schedules;
            if (employeeId != null && startDate != null && endDate != null) {
                schedules = scheduleService.findByEmployeeIdAndDateRange(employeeId, startDate, endDate);
            } else if (roomId != null && startDate != null && endDate != null) {
                schedules = scheduleService.findByRoomIdAndDateRange(roomId, startDate, endDate);
            } else if (employeeId != null) {
                schedules = scheduleService.findByEmployeeId(employeeId);
            } else if (roomId != null) {
                schedules = scheduleService.findByRoomId(roomId);
            } else if (scheduleDate != null) {
                schedules = scheduleService.findByScheduleDate(scheduleDate);
            } else {
                schedules = scheduleService.findAll();
            }
            return Result.success(schedules);
        } catch (Exception e) {
            log.error("查询排班列表失败", e);
            return Result.error("查询排班列表失败: " + e.getMessage());
        }
    }

    /**
     * 更新排班信息
     */
    @PutMapping("/{id}")
    public Result<Schedule> updateSchedule(@PathVariable Long id, @Valid @RequestBody Schedule schedule) {
        log.info("更新排班信息，ID: {}", id);
        try {
            schedule.setId(id);
            // 检查排班冲突
            if (scheduleService.hasScheduleConflict(schedule)) {
                return Result.badRequest("排班时间冲突，请检查员工或房间的排班安排");
            }
            Schedule updatedSchedule = scheduleService.update(schedule);
            return Result.success(updatedSchedule);
        } catch (Exception e) {
            log.error("更新排班信息失败", e);
            return Result.error("更新排班信息失败: " + e.getMessage());
        }
    }

    /**
     * 删除排班
     */
    @DeleteMapping("/{id}")
    public Result<Void> deleteSchedule(@PathVariable Long id) {
        log.info("删除排班，ID: {}", id);
        try {
            scheduleService.deleteById(id);
            return Result.success(null);
        } catch (Exception e) {
            log.error("删除排班失败", e);
            return Result.error("删除排班失败: " + e.getMessage());
        }
    }

    /**
     * 自动排班
     */
    @PostMapping("/auto")
    public Result<Map<String, Object>> autoSchedule(
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate) {
        log.info("自动排班，时间段: {} - {}", startDate, endDate);
        try {
            Map<String, Object> result = scheduleService.autoSchedule(startDate, endDate);
            return Result.success(result);
        } catch (Exception e) {
            log.error("自动排班失败", e);
            return Result.error("自动排班失败: " + e.getMessage());
        }
    }

    /**
     * 高级自动排班 - 支持自定义参数
     */
    @PostMapping("/auto/advanced")
    public Result<Map<String, Object>> advancedAutoSchedule(
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate,
            @RequestParam(required = false) List<Integer> employeeTypes,
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.TIME) LocalTime startTime,
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.TIME) LocalTime endTime) {
        
        log.info("高级自动排班，时间段: {} - {}, 员工类型: {}, 工作时间: {} - {}", 
                startDate, endDate, employeeTypes, startTime, endTime);
        
        try {
            // 设置默认值
            if (employeeTypes == null || employeeTypes.isEmpty()) {
                employeeTypes = Arrays.asList(1, 2, 3);
            }
            if (startTime == null) {
                startTime = LocalTime.of(8, 0);
            }
            if (endTime == null) {
                endTime = LocalTime.of(18, 0);
            }
            
            // 执行自动排班
            List<Schedule> generatedSchedules = schedulingAlgorithmService.autoSchedule(
                startDate, endDate, employeeTypes, startTime, endTime
            );
            
            // 获取统计信息
            Map<String, Object> statistics = schedulingAlgorithmService.getSchedulingStatistics(startDate, endDate);
            
            Map<String, Object> result = Map.of(
                "success", true,
                "message", "高级自动排班完成",
                "generatedCount", generatedSchedules.size(),
                "schedules", generatedSchedules,
                "statistics", statistics
            );
            
            return Result.success(result);
            
        } catch (Exception e) {
            log.error("高级自动排班失败", e);
            return Result.error("高级自动排班失败: " + e.getMessage());
        }
    }

    /**
     * 优化排班负载均衡
     */
    @PostMapping("/optimize")
    public Result<Map<String, Object>> optimizeSchedule(
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate) {
        
        log.info("优化排班负载均衡，时间段: {} - {}", startDate, endDate);
        
        try {
            schedulingAlgorithmService.optimizeScheduleBalance(startDate, endDate);
            
            // 获取优化后的统计信息
            Map<String, Object> statistics = schedulingAlgorithmService.getSchedulingStatistics(startDate, endDate);
            
            Map<String, Object> result = Map.of(
                "success", true,
                "message", "排班优化完成",
                "statistics", statistics
            );
            
            return Result.success(result);
            
        } catch (Exception e) {
            log.error("排班优化失败", e);
            return Result.error("排班优化失败: " + e.getMessage());
        }
    }

    /**
     * 获取排班算法统计信息
     */
    @GetMapping("/algorithm/statistics")
    public Result<Map<String, Object>> getAlgorithmStatistics(
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate) {
        
        log.info("获取排班算法统计信息，时间段: {} - {}", startDate, endDate);
        
        try {
            Map<String, Object> statistics = schedulingAlgorithmService.getSchedulingStatistics(startDate, endDate);
            return Result.success(statistics);
        } catch (Exception e) {
            log.error("获取排班算法统计信息失败", e);
            return Result.error("获取排班算法统计信息失败: " + e.getMessage());
        }
    }

    /**
     * 获取员工排班表视图
     */
    @GetMapping("/employee/{employeeId}")
    public Result<Map<String, Object>> getEmployeeScheduleView(
            @PathVariable Long employeeId,
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate) {
        log.info("获取员工排班表视图，员工ID: {}, 时间段: {} - {}", employeeId, startDate, endDate);
        try {
            Map<String, Object> scheduleView = scheduleService.getEmployeeScheduleView(employeeId, startDate, endDate);
            return Result.success(scheduleView);
        } catch (Exception e) {
            log.error("获取员工排班表视图失败", e);
            return Result.error("获取员工排班表视图失败: " + e.getMessage());
        }
    }

    /**
     * 获取管理员排班表视图
     */
    @GetMapping("/admin")
    public Result<Map<String, Object>> getAdminScheduleView(
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate) {
        log.info("获取管理员排班表视图，时间段: {} - {}", startDate, endDate);
        try {
            Map<String, Object> scheduleView = scheduleService.getAdminScheduleView(startDate, endDate);
            return Result.success(scheduleView);
        } catch (Exception e) {
            log.error("获取管理员排班表视图失败", e);
            return Result.error("获取管理员排班表视图失败: " + e.getMessage());
        }
    }

    /**
     * 获取排班统计信息
     */
    @GetMapping("/statistics")
    public Result<Map<String, Object>> getScheduleStatistics(
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate) {
        log.info("获取排班统计信息，时间段: {} - {}", startDate, endDate);
        try {
            Map<String, Object> statistics = scheduleService.getScheduleStatistics(startDate, endDate);
            return Result.success(statistics);
        } catch (Exception e) {
            log.error("获取排班统计信息失败", e);
            return Result.error("获取排班统计信息失败: " + e.getMessage());
        }
    }
}